using KineBall.GameLogic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace KineBall.Rendering
{
    public class RendererState
    {
        public Camera camera;
        public BoundingSphere sphereBounding;
        public bool scoreAnimationFinish;
    }

    public class Renderer : Microsoft.Xna.Framework.DrawableGameComponent
    {
        BasicEffect effect;
        SpriteBatch spriteBatch;
        Camera camera;

        GameFieldModel gameFieldModel;
        ShieldModel redShieldModel;
        ShieldModel blueShieldModel;
        BallModel ballModel;
        MessagesRendering messagesRendering;

        GameState state;

        Texture2D squareTexture;
        Texture2D scoreBallTexture;

        SpriteFont gameFont;

        public RendererState renderState;

        float elapsedTime = 0;

        public Renderer(Game game)
            : base(game)
        {
            camera = new Camera();
            renderState = new RendererState();
            renderState.camera = camera;
            renderState.sphereBounding = new BoundingSphere();
            renderState.scoreAnimationFinish = false;

            if (Game.Services.GetService(typeof(RendererState)) == null)
                Game.Services.AddService(typeof(RendererState), renderState);
        }

        public override void Initialize()
        {
            state = (GameState)Game.Services.GetService(typeof(GameState));

            base.Initialize();
        }

        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(RendererState));
            base.Dispose(disposing);
        }

        protected override void LoadContent()
        {
            GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
            GraphicsDevice.BlendState = BlendState.AlphaBlend;

            effect = new BasicEffect(GraphicsDevice);
            spriteBatch = new SpriteBatch(GraphicsDevice);
            camera.Initialize(new Vector3(0, 0, 5.3f), Vector3.Zero, Vector3.Up, GraphicsDevice);

            gameFieldModel = new GameFieldModel(GraphicsDevice, state.gameField);

            redShieldModel = new ShieldModel(GraphicsDevice, Game.Content.Load<Texture2D>(@"Textures/Shields/RedShield"), state.redShieldLeft);
            blueShieldModel = new ShieldModel(GraphicsDevice, Game.Content.Load<Texture2D>(@"Textures/Shields/LightBlueShield"), state.blueShield);

            ballModel = new BallModel(Game.Content.Load<Model>(@"Models/Sphere"), 0.2f);
            renderState.sphereBounding = ballModel.Model.Meshes[0].BoundingSphere;

            Texture2D[] messagesTexture = new Texture2D[9];
            messagesTexture[(uint)Messages.Starting] = Game.Content.Load<Texture2D>(@"Textures/GameInterface/Start");
            messagesTexture[(uint)Messages.CountDownOne] = Game.Content.Load<Texture2D>(@"Textures/CountDown/one");
            messagesTexture[(uint)Messages.CountDownTwo] = Game.Content.Load<Texture2D>(@"Textures/CountDown/two");
            messagesTexture[(uint)Messages.CountDownThree] = Game.Content.Load<Texture2D>(@"Textures/CountDown/three");
            messagesTexture[(uint)Messages.BluePoint] = Game.Content.Load<Texture2D>(@"Textures/GameInterface/bluepoint");
            messagesTexture[(uint)Messages.RedPoint] = Game.Content.Load<Texture2D>(@"Textures/GameInterface/redpoint");
            messagesTexture[(uint)Messages.Lose] = Game.Content.Load<Texture2D>(@"Textures/GameInterface/lose");
            messagesTexture[(uint)Messages.Win] = Game.Content.Load<Texture2D>(@"Textures/GameInterface/win");
            messagesTexture[(uint)Messages.Pause] = Game.Content.Load<Texture2D>(@"Textures/GameInterface/pause");
            messagesRendering = new MessagesRendering(messagesTexture, new Vector2(GraphicsDevice.Viewport.Width * 0.5f, GraphicsDevice.Viewport.Height * 0.5f));

            squareTexture = Game.Content.Load<Texture2D>(@"Textures/GameInterface/Square");
            scoreBallTexture = Game.Content.Load<Texture2D>(@"Textures/GameInterface/ScoreBall");

            gameFont = Game.Content.Load<SpriteFont>(@"Fonts/gamefont");

            base.LoadContent();
        }

        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            effect.Projection = camera.Projection;
            effect.View = camera.View;

            gameFieldModel.Draw(effect, GraphicsDevice, state.gameField, state.ball.Position);
            blueShieldModel.Draw(effect, state.blueShield, GraphicsDevice);

            switch (state.flow)
            {
                case GameFlow.CountDown:
                    messagesRendering.DrawCountDown(state.gameMessageState, spriteBatch);
                    break;
                case GameFlow.StartingMatch:
                    messagesRendering.DrawStarting(state.gameMessageState, spriteBatch);
                    break;
                case GameFlow.PlayingMatch:
                    ballModel.DrawBall(camera, state.ball);
                    break;
                case GameFlow.RedPoint:
                    messagesRendering.DrawPoint(state.gameMessageState, spriteBatch, true);
                    break;
                case GameFlow.BluePoint:
                    messagesRendering.DrawPoint(state.gameMessageState, spriteBatch, false);
                    break;
                case GameFlow.FinishingGame:
                    if (state.redShieldRight.Score == 4)
                        messagesRendering.DrawLoseWin(state.gameMessageState, spriteBatch, true);
                    else
                        messagesRendering.DrawLoseWin(state.gameMessageState, spriteBatch, false);
                    break;
                case GameFlow.Pause:
                    messagesRendering.DrawPauseMessage(state.gameMessageState, spriteBatch);
                    break;
            }

            redShieldModel.Draw(effect, state.redShieldRight, GraphicsDevice);
            redShieldModel.Draw(effect, state.redShieldLeft, GraphicsDevice);

            DrawScore((float)gameTime.ElapsedGameTime.TotalSeconds);

            base.Draw(gameTime);
        }

        private void DrawScore(float deltaT)
        {
            spriteBatch.Begin();

            // Punteggio player
            spriteBatch.Draw(squareTexture, new Rectangle(15, 15, 60, 690), Color.Red);
            for (int i = 0; i < state.redShieldRight.Score; ++i)
            {
                spriteBatch.Draw(scoreBallTexture, new Rectangle(20, 630 - 60 * i, 50, 50), Color.White);
            }

            // Punteggio avversario
            spriteBatch.Draw(squareTexture, new Rectangle(1205, 15, 60, 690), Color.Blue);
            for (int i = 0; i < state.blueShield.Score; ++i)
            {
                spriteBatch.Draw(scoreBallTexture, new Rectangle(1210, 630 - 60 * i, 50, 50), Color.White);
            }

            spriteBatch.End();
        }
    }
}
